// ----------------------------------------------------------------------------
// serialize_scalar_value.cpp
// ----------------------------------------------------------------------------
#include <fw/base/serialize/serialize_scalar_value.h>
#include <stdio.h>
#include <fw/base/serialize/byte_reader.h>
#include <fw/base/serialize/byte_writer.h>
#include <fw/base/runtime/hash.h>

namespace fw
{
	SerializeScalarValue::SerializeScalarValue()
	: m_type(kZero)
	{
		m_value.i64 = 0ul;
	}
	
	SerializeScalarValue SerializeScalarValue::Float(double value)
	{
		SerializeScalarValue v;
		if(value != 0.0)
		{
			v.m_type		= kFloat;
			v.m_value.f64	= value;
		}
		return v;
	}
	
	SerializeScalarValue SerializeScalarValue::Int(int64_t value)
	{
		SerializeScalarValue v;
		if(value != 0.0)
		{
			v.m_type		= kInt;
			v.m_value.i64	= value;
		}
		return v;
	}
	
	SerializeScalarValue SerializeScalarValue::Zero()
	{
		return SerializeScalarValue();
	}
	
	bool SerializeScalarValue::operator==(const SerializeScalarValue &other) const
	{
		return (m_value.i64 == other.m_value.i64) ? true : false;
	}
	
	bool SerializeScalarValue::operator!=(const SerializeScalarValue& other) const
	{
		return !(*this == other);
	}
	
	double SerializeScalarValue::AsFloat() const
	{
		switch (m_type)
		{
			case kFloat:	return m_value.f64;
			case kInt:		return static_cast<double>(m_value.i64);
			case kZero:		return 0.0;
		}
		return 0.0;
	}

	int64_t	SerializeScalarValue::AsInt() const
	{
		switch (m_type)
		{
		case kFloat:	return static_cast<int64_t>(m_value.f64);
		case kInt:		return m_value.i64;
		case kZero:		return 0;
		}
		return 0;
	}
	
	void SerializeScalarValue::Write(ByteWriter &writer) const
	{
		writer.Write8(m_type);
		switch (m_type)
		{
		case kFloat:
		case kInt:
			writer.Write64(m_value.i64);
			break;
		case kZero:
			break;
		}
	}
	
	SerializeScalarValue SerializeScalarValue::Read(ByteReader &reader)
	{
		SerializeScalarValue v;
		Type t = static_cast<Type>(reader.Read8());
		switch (t)
		{
		case kFloat:
		case kInt:
			v.m_value.i64 = reader.Read64();
			break;
		case kZero:
			break;
		}
		return v;
	}
	
	uint64_t SerializeScalarValue::GetChecksum(uint64_t basis) const
	{
		basis = HashValue64(m_type,      basis);
		basis = HashValue64(m_value.i64, basis);
		return basis;
	}
	
} // namespace fw
